/***************************************************************
*Copyright(c) 2020思特诺(Stduino)All right reserved.
*
*This library is open source and free for individual users. 
*
*For commercial use, please contact service001@stduino.com.
***************************************************************/

#include "StduinoMemory.h"

struct STDUINOMEMORY StduinoMemory=
{
INIT,
PERUSED,
{0},
{0},
0,
};

void MEMCPY(void *des,void *src,unsigned long len)  
{
 unsigned char *Sdes=des;
 unsigned char *Ssrc=src;
 
 while(len--)
 {
  *Sdes++=*Ssrc++;
 }
}

void MEMSET(void *s,unsigned char c,unsigned long count)  
{  
 unsigned char *Ss = s;
 
 while(count--)
 {
  *Ss++=c;  
 }
}

void *MEMMOVE( void *dest , const void *src , unsigned int count)
{
 if(0 == count)
 {
  return 0;
 }
 
 if(0 == dest || 0 == src )
 {
  return 0;
 }
 
 char *dest_ ;
 char *src_ ;
 
 if(dest < src )
 {
  dest_ =(char*) dest; src_ = (char*)src;
  
  while( count-- )
  {
   *dest_++ = *src_++;
  }
 }else if( dest > src )
 {
  dest_ = (char*)dest + count;
  src_ = (char*)src + count;
  
  while(count -- )
  {
   *--dest_ = *--src_;
  }
 }
 
 return dest;
}

void INIT(void)  
{  
 MEMSET(StduinoMemory.MemoryBasic, 0, sizeof(StduinoMemory.MemoryBasic));
 StduinoMemory.MemoryReadyFlag=1;
}

unsigned char PERUSED(void)  
{  
 unsigned short used=0;
 unsigned long i;
 
 for(i=0;i<MemoryMapSize;i++)  
 {  
  if(StduinoMemory.MemoryMap)
  {
   used++; 
  }
 }
 
 return used*100/MemoryMapSize;  
}

unsigned long MALLOC(unsigned long size)  
{  
 signed long offset=0;  
 unsigned short nmemb; 
 unsigned short cmemb=0;
 unsigned long i; 
 
 if(!StduinoMemory.MemoryReadyFlag)
 {
  StduinoMemory.Begin();
 }
 
 if(size==0)
 {
  return 0XFFFFFFFF;
 }
 
 nmemb=size/BlockSize;
 
 if(size%BlockSize)
 {
  nmemb++;
 }
 
 for(offset=MemoryMapSize-1;offset>=0;offset--)
 { 
  if(!StduinoMemory.MemoryMap[offset])
  {
   cmemb++;
  }else
  {
   cmemb=0;
  }
  
  if(cmemb==nmemb)
  {          
   for(i=0;i<nmemb;i++) 
   {             
    StduinoMemory.MemoryMap[offset+i]=nmemb;     
   }
   
   return (offset*BlockSize);
  }
 }
 
 return 0XFFFFFFFF; 
}

unsigned char FREE(unsigned long offset)  
{  
 int i;
 
 if(!StduinoMemory.MemoryReadyFlag)
 {
  StduinoMemory.Begin();    
  return 1;
 }
 
 if(offset<MemorySize)
 {  
  int index=offset/BlockSize;
  int nmemb=StduinoMemory.MemoryMap[index];
  
  for(i=0;i<nmemb;i++)
  {  
   StduinoMemory.MemoryMap[index+i]=0;  
  } 
  
  return 0;  
 }else 
 {
  return 2;
 }
}

void Stduino_free(void *ptr)  
{  
 unsigned long offset;
 
 if(ptr==0)
 {
  return;
 }
 
 offset=(unsigned long)ptr-(unsigned long)&StduinoMemory.MemoryBasic;  
 FREE(offset);
}

void *Stduino_malloc(unsigned long size)  
{  
 unsigned long offset;
 offset=MALLOC(size);
 
 if(offset==0XFFFFFFFF)
 {
  return 0;
 }else
 {
  return (void*)((unsigned long)&StduinoMemory.MemoryBasic+offset);
 }
}

void *Stduino_realloc(void *ptr,unsigned long size)  
{  
 unsigned long offset;  
 offset=MALLOC(size);
 
 if(offset==0XFFFFFFFF)
 {
  return 0;    
 }else  
 {  
  MEMCPY((void*)((unsigned long)&StduinoMemory.MemoryBasic+offset),ptr,size); 
  Stduino_free(ptr);
  return (void*)((unsigned long)&StduinoMemory.MemoryBasic+offset);
 }  
} 

/***************************************************************
*Copyright(c) 2020思特诺(Stduino)All right reserved.
*
*This library is open source and free for individual users. 
*
*For commercial use, please contact service001@stduino.com.
***************************************************************/
